import { conn } from '@beshell/conn-ts/Connection'
import { AppModel } from '../../model/AppModel'
// import scratch3 from "./program/scratch"
import { bus } from '@beshell/events-ts/bus'
import { runtime } from '../../types'

const CodeMainJS = `
const model = require('./model.js')
model.setup()
model.runCards()
`



export async function saveModel(model:AppModel, graphData: any, blocklyXml: string) {

    if(model.bMockup) {
        window.$message.success("演示模型已经保存")
        return
    }

    if((window as any).debug) {
        console.log(generateModelCode(model))
        return
    }

    if(!model) {
        console.log(new Error("model is null"))
        return
    }
    
    bus.emit("spin-fullpage.show()", "准备将模型保存到远程零件 ...")
    
    try {

        // beconsole/*.json|xml
        model.blocklyXML = blocklyXml
        console.log(model.blocklyXML)
        await model.save(
            {
                graph: graphData
            } ,
            (msg: string)=>{
                bus.emit("spin-fullpage.message()", msg)
            }
        )

        // model.js
        try{
            await makeModelFile(model)
        }catch(e:any){
            window.$message.error("生成JS代码时遇到了错误："+e.message)

            console.error(e)
            throw e
        }

        // main.js
        await makeMainFile(model)

        // reset to level 5
        bus.emit("spin-fullpage.message()", "正在重置远程主机零件 ...")
        await conn.console.reset(5, 10000)

        await model.remoteSetup() ;
        
        window.$message.success("模型:"+model.pkgmeta.title+" 已经保存")

    } catch (e) {
        console.error(e)
    }
    
    bus.emit("spin-fullpage.hide()")
}

function generateModelCode(model:AppModel) {

    let codeSetup = model?.generateSetupCode(1) + "\n\n" + model?.generateBeginCode(1)

    // UI 代码
    // let codeSetupUI = model.ui.generateSetupCode(1)

    // 生成代码
    // let codeMain = scratch3.generateCode("JavaScript")
    let codeMain = ''

    return `
/**
 * 此文件由 BeConsole 自动生成，任何改动都会被 BeConsole 覆盖
 */
require("besdk")

// 在初始化 BeConsole "硬件" 视图中创建并配置的零件
exports.setup = function () {
${codeSetup}
}

// 根据 BeConsole "编程" 视图中的程序卡片生成的JS代码
exports.runCards = async function(){
${codeMain}
}
`
}

async function makeModelFile(model:AppModel) {
    
    if(!conn.isConnected)
        return

    let code = generateModelCode(model)
    console.log(code)

    // 写入文件
    await uploadFile(model?.folderPath + '/model.js', code)
}

async function makeMainFile(model:AppModel) {

    if(!conn.isConnected)
        return

    // 检查文件是否存在
    let mainJsPath = model?.folderPath + '/main.js'
    if( await conn.console.call(`fs.isFileSync("${mainJsPath}")`) ) {

        console.log("文件已经存在", mainJsPath)
        
        // 检查文件变动，询问用户是否覆盖
        // todo ...

        return mainJsPath
    }

    // 写入文件
    await uploadFile(mainJsPath, CodeMainJS)

    // 设置为启动模型
    // await conn.console.call(`require("/etc/init.d/app.js").setAutoBootPath("${mainJsPath}")`)

    return mainJsPath
}

function uploadFile(remotePath: string, content: string) {
    return conn.active?.writeFile(remotePath, content, (progress: number)=>{
        bus.emit("spin-fullpage.message()", `${remotePath} [${Math.round(progress*100)}%]`)
    })
}